//加热风扇控制, 排气风扇控制, 点火控制

#include "../main.h"

#include <stdlib.h>
#define LowTempThreshold 120 //华氏度的判断低温阈值
#define TempSet_Min 165      //设定值最小值
#define HEAT_450 450

//温度设定值
uint16_t temp_set = 165; //= Temp_Set_Smoke; //默认 Smoke档位
uint16_t down_temperature_Ki = 0; //降温积分累计,2min降1
float grill_down_temperature = 0.0;
_Fan_State_S Fan_State;

#if Debug_Hand_PID == 1
float Hand_PID_TD;
#endif

enum
{
    DISP_POWER_UP = 0,
    DISP_STAND_BY,
    DISP_MAIN_MODE,
    DISP_SET_TIMER_MODE,
    DISP_SET_PROBEALARM_MODE,
    DISP_GRILLRUNNING_MODE,
    DISP_SHUTDOWN_MODE,
    DISP_SysSelfTest_MODE,
} DisplayModeEnum;
uint8_t DisplayMode;
struct
{
    uint8_t SYS_ERROR : 1;
    uint8_t SYS_STANDBY : 1;
    uint8_t SMOKE_SEL_PRESSED : 1; //RTD_SEL_PRESSED
    uint8_t KEY_PRESSED : 1;
    uint8_t TEMP_MODE_SWITCHED : 1;
    uint8_t DISP_PROBE_STATE : 1;
    uint8_t SELF_TEST_EN : 1;
    uint8_t DISP_TIMER_STATE : 1;
} flag;
uint16_t ExhaustFanClock = 0; //倒计时 10min, Tick 1s, 允许数据溢出
uint16_t FanClock_Smoke = 0; //Tick 1s, 5s ON, 10s OFF
uint16_t PowerDown_Clock = 600; //关机倒计时 10min, Tick 1s
uint16_t Tick_1S_Count = 100; //默认上电 100s, 1s计数1次 //Changed this for the initial PID compute time is not less than 0
uint16_t Tick_10mS_Count = 0;
const uint8_t UPDATE_DISPLAY = 100; //2;  //DW: Changed to update Temp every half second
const uint16_t Ignite_Time = 240;   //240s,上电后点火持续时间
uint8_t Ignitor_cnt = 0;
uint8_t down_temperature_selected = false;
uint8_t DisplayFirmwareVersion = 0;
uint8_t PrimingAuger = 0;
uint8_t Temp_Change_Flag = 0;
uint8_t Griddle_Flag = 0;
uint8_t Flameout_flag = 0;
uint8_t Burn_Delay_Timer = 0;
float pre_grill_temp = 0.0;
float pre_grill_griddle_temp = 0.0;
//PID专用的温度设定值
float f_SettingTemp = SmokeTempSetting; //最低PID温度设定值
#define COOLING_TIME 600                //600
uint8_t HeatingFanStep;                 //0:停止输出, >0: 进料马达工作
uint8_t ExhaustFanStep;                 //0:停止输出, >0: 排气扇工作
uint8_t IgniterStep;                    //0:停止输出, >0:点火工作

uint16_t IgniterClock; //Tick 1s
//Smoke Ctrl Variable
//Tick 10ms //2min30s = 150s = 150 * (100 * 10ms)
uint16_t HeaterFanClock; //Tick 1s
uint16_t HeaterFanStep;
uint8_t Smoke_P_Value;            //烟熏档位值:[0,5],默认0


int GetTemp(int F)
{
    float temp;

    if(UI_System.Grill_Unit == Unit_C)
    {
        temp = (F - 32);
        temp /= 1.8;
        return temp;
    }
    return F;
}


void FanCtrl_IOConfig(void)
{
     gpio_config_t io_conf;

    //disable interrupt
    io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
    //set as output mode
    io_conf.mode = GPIO_MODE_OUTPUT;
    //bit mask of the pins that you want to set,e.g.GPIO18/19
    io_conf.pin_bit_mask = FanCtrl_GPIO_PIN_SEL;
    //disable pull-down mode
    io_conf.pull_down_en = 0;
    //disable pull-up mode
    io_conf.pull_up_en = 0;
    //configure GPIO with the given settings
    gpio_config(&io_conf);  
    IgniterClose;
    HeaterFanClose;
    ExhaustFanClose;
}

//温控设备上电初始化
void FanCtrlInit(void)
{
    FanCtrl_IOConfig();
    //所有温控设备默认停止输出
    IgniterClose;
    HeaterFanClose;
    ExhaustFanClose;

    Tick_1S_Count = 0;
    HeatingFanStep = 0;
    IgniterStep = 0;
    ExhaustFanStep = 0;

    HeaterFanStep = 0;
    HeaterFanClock = 0;
    ExhaustFanClock = 0;
    IgniterClock = 0;

    RTD[RTD_Seq_RTD].status = Pt_Normal;
}

//所有温控设备的时钟源, Tick 10ms
void FanCtrlClock(void)
{
    static uint8_t Count;
    static uint16_t count_DownTemp = 0;

    if(Tick_10mS_Count < 0xffff) Tick_10mS_Count++;
    Count++;
    if (Count >= 100)
    {
        Count = 0;
        if(Tick_1S_Count < 0xffff) Tick_1S_Count++; //标记产生1s计时

        if (ExhaustFanClock > 0) ExhaustFanClock--;
        if(PowerDown_Clock > 0) PowerDown_Clock--;
        if ((IgniterClock >= 1) && (IgniterClock < 0xffff)) IgniterClock++;
        //烟熏控制相关变量
        if (HeaterFanClock < 0xffff) HeaterFanClock++;
        if((FanClock_Smoke > 0) && (FanClock_Smoke < 0xffff)) FanClock_Smoke++; 
    }
}
//启动温控设备
void FanCtrlStart(void)
{
    if (RTD[RTD_Seq_RTD].status == Pt_Normal)
    { //烤炉温度正常,才能启动点火   
        if (HeatingFanStep == 0) HeatingFanStep = 1; //默认,正常温控
        if (IgniterStep == 0) IgniterStep = 1;
        if (ExhaustFanStep == 0)
        {
            ExhaustFanStep = 1;
            ExhaustFanClock = 0;
        }
    }
}
//停止温控设备
void FanCtrlStop(uint16_t param)
{
    HeatingFanStep = 0;
    IgniterStep = 0;
    if (ExhaustFanStep > 0)
    { //排气扇打开后,才能停止排气扇
        ExhaustFanStep = 0;
        // if(ExhaustFanClock == 0) ExhaustFanClock = FanClose_Delay_Time; //10min = 60s * 10 = 600s,多10s用于显示OFF
        if (ExhaustFanClock == 0)
            ExhaustFanClock = param; //10min = 60s * 10 = 600s,多10s用于显示OFF
    }
}
//强制停止温控设备
void FanCtrlForceStop(void)
{
    HeatingFanStep = 0;
    IgniterStep = 0;
    ExhaustFanClock = 0;
    ExhaustFanStep = 0;
}

//进料控制调用该函数, 打开排气扇
void Heating_Ctrl_Exhaust_Open(void)
{
    ExhaustFanStep = 1;
}
//进料控制调用该函数, 关闭排气扇
void Heating_Ctrl_Exhaust_Close(void)
{
    ExhaustFanStep = 0;
}

void HeatingFanCtrl(void)
{
    uint8_t tempmode = 0;
    uint16_t tempf = 0, tempc = 0;

    //DW: PID Control Variables
    static uint16_t previous_tempmode_f = 0;
    static uint8_t fan_con_state = 0;
    static uint16_t fan_con_timer = 0;
    static uint8_t fan_con_state1 = 0;
    static uint16_t fan_con_timer1 = 0;
    static int32_t pid_output = 0;
    static uint32_t pid_output_Min = 0;
    static int32_t pid_output_increment = 0;
    static uint16_t pid_output_time = 0;
    static uint16_t start_sequence_on_time = 0;
    static uint16_t grill_temperature_senser_timer = 0;
    //DW: PID Time Constants
    static uint16_t PID_Tc_10ms = 3500; //10ms clock
    uint16_t PID_span = 0;

    static uint16_t down_temperature_delay = 0; //Delay for running the PID after a selection from a higher temperature selection to a lower.

    static float grill_temperature = 0.0;
    static float grill_temperature_old = 0.0;

    static bool pid_parameter_changed = 1;
    static bool fan_con_flag = 0;
    static bool cold_ambient_temperature = false;
    static bool artic_ambient_temperature = false;

    float Kc = 0;   //Kc = PID_P
    float tauI = 0; //tauI = (1.0 / PID_I) * PID_Tc_10ms;
    float tauD = 0; //tauD = PID_D / PID_Tc_10ms

    static float temp_min = 999;
    static float temp_max = 0;
    static float grill_temp_Old = 0;
    static float grill_temperature_Filter = 0.0;

    if (RTD[RTD_Seq_RTD].status != Pt_Normal)
    {
        HeatingFanStep = 0;
    }

    switch (HeatingFanStep)
    {
        case 0: //Close HeatingFan
            HeaterFanClose;
            HeaterFanClock = 0;
            pid_output = 0;
            pid_output_time = 0;
            start_sequence_on_time = 0;
            PID_Tc_10ms = 3500;
            down_temperature_delay = 0;
            down_temperature_selected = false;
            cold_ambient_temperature = false;
            artic_ambient_temperature = false;
            break;
        case 1: //DW: State 0: Initial State
            fan_con_state = 0;
            fan_con_timer = 0;
            fan_con_state1 = 0;
            fan_con_timer1 = 0;
            HeatingFanStep = 2;
            artic_ambient_temperature = false;

            if (RTD[RTD_Seq_RTD].value <= GetTemp(20))
            {
                cold_ambient_temperature = true;
                artic_ambient_temperature = true;
            }
            else if (RTD[RTD_Seq_RTD].value < GetTemp(45)) //Check to see if the grill temp is below thresholds needed for cold start
            {
                start_sequence_on_time = 230; //Cold ambient Temperature
                cold_ambient_temperature = true;
            }
            else if (RTD[RTD_Seq_RTD].value < GetTemp(120))
            {
                start_sequence_on_time = 90; //Normal ambient Temperature
                cold_ambient_temperature = false;
            }
            else
            {
                start_sequence_on_time = 75; //hight  ambient Temperature
                cold_ambient_temperature = false;
            }
            HeaterFanOpen;
            Tick_1S_Count = 0;
            break;
        case 2: //DW: Ignition Sequence
            if (artic_ambient_temperature == false)
            {
                if (Tick_1S_Count > start_sequence_on_time) //Check if has run for start sequece on time
                {
                    HeaterFanClose;
                }
                if (Tick_1S_Count > 240) //Check if ignition sequence has completed ran for 4 min.
                {
                    HeatingFanStep = 3;
                    previous_tempmode_f = 1;
                }
            }
            else
            {
                if (RTD[RTD_Seq_RTD].value > GetTemp(130)) //For cold startup run the RTD temperature up to 140, there should be enough pellets in the cup to get up to 200.
                {
                    HeatingFanStep = 3;
                    previous_tempmode_f = 1;
                }
            }
            fan_con_state = 0;
            Tick_10mS_Count = 0;
            break;
        case 3:
            HeaterFanClose;
            pid_output = 0;
            HeatingFanStep = 4;
            break;
        case 4:
            pid_output_Min = 300;
            Kc = 1.5;
            tauI = 0.08;
            tauD = 4;
            // PID_Tc_10ms = 2500;
            PID_Tc_10ms = 1500;

			setTunings(Kc,tauI,tauD);
            if (previous_tempmode_f != temp_set)
            {
                previous_tempmode_f = temp_set;
                // PID_Tc_10ms = 2800;
                setInputLimits(GetTemp(130), GetTemp(450)); //GetTemp(520)
                setOutputLimits(pid_output_Min, PID_Tc_10ms);
                PID_constants(Kc, tauI, tauD, PID_Tc_10ms, 0);
                //Change PID settings per temp_set in here, if needed
                PID_setSetPoint(temp_set);
                PID_reset();
            }
            if (Tick_10mS_Count >= PID_Tc_10ms)
            {
                // grill_temperature = UI_System.RTD.Actual;
                grill_temperature = RTD[RTD_Seq_RTD].value;
                if (grill_temperature > (temp_set + GetTemp(20))) PID_reset();
                PID_setProcessValue(grill_temperature);
                pid_output = (int32_t)PID_compute();
                HeaterFanOpen;
                Tick_10mS_Count = 0;
                if(pid_output < pid_output_Min) pid_output = pid_output_Min;
            }
            if (Tick_10mS_Count > pid_output)
            {
                HeaterFanClose;
            }
            break;
        default:
            HeatingFanStep = 0;
            break;
    }
}

//点火控制(紫线),实际是加热棒控制
//默认上电初始化关闭所有温控输出设备
//上电点火4min后停止点火
//若温度低于150F，保持上次运行状态60s后再打开点火
//直到温度高于150F之前,始终是间隔60s后再打开点火; 目的为了防止点火点不着,或者点火异常(感觉有点多余,理论上只要CPU的IO不出问题,不太可能输出停止)
//在[150F,160F]之间,点火一直打开
//温度高于160F,停止点火(这就有问题了,温度高的情况下,停止点火,温度肯定会突然下降,难怪温度在高温很难控制)
//  补充: 在进料的时候会控制点火
//通过 SYS_STANDBY 置1, 控制停止点火
void IgniterCtrl(void)
{
    static uint8_t IgniterClock_Step = 0;

    if (RTD[RTD_Seq_RTD].status != Pt_Normal)
    {
        IgniterStep = 0;
    }
    switch (IgniterStep)
    {
        case 0:
            IgniterClose;
            break;
        case 1: //Stand-Bye
            IgniterOpen;
            IgniterClock = 0;
            IgniterStep = 2;
            break;
        case 2: //Ignite grilll
            if (IgniterClock == 0) IgniterClock = 1;
            else if (IgniterClock > 240)
            { //上电点火加热240s后执行
                IgniterClose;
                IgniterStep = 3; //Ignite time complete
                IgniterClock = 0;
                IgniterClock_Step = 0;
            }
            break;
        case 3: //Running
            if (RTD[RTD_Seq_RTD].value < GetTemp(150))
            { //为避免点火棒烧断: 点火棒通电后,持续时间限制在 断电2min,点火4min,
                if(IgniterClock_Step == 0)
                { //断电2min
                    if (IgniterClock == 0)
                    {
                        IgniterClose;
                        IgniterClock = 1;
                    }
                    else if (IgniterClock >= 120)
                    { 
                        IgniterClock = 0;
                        IgniterClock_Step++;
                    }
                }
                else if(IgniterClock_Step == 1)
                { //点火4min
                    if (IgniterClock == 0)
                    {
                        IgniterOpen;
                        IgniterClock = 1;
                    }
                    else if (IgniterClock >= 240)
                    {
                        IgniterClock = 0;
                        IgniterClock_Step = 0;
                    }
                }
            }
            else if (RTD[RTD_Seq_RTD].value > GetTemp(160))
            {
                IgniterClose;
                IgniterClock_Step = 0;
            }
            break;
        default:
            IgniterStep = 0;
            break;
    }
}

//排气风扇（橙线）
//作用: 关机后,持续打开一段时间后再停止输出
//风力太大,可能需要PWM控制输出,降低风力
//系统错误,停止排气
//判断SYS_STANDBY的值,决定是否打开排气
//上电默认SYS_STANDBY为0, 排气打开
//当SYS_STANDBY == 1时, 打开排气扇持续300s后关闭排气扇
void ExhaustFanCtrl(void)
{
    if (RTD[RTD_Seq_RTD].status != Pt_Normal)
    {
        if (ExhaustFanStep > 0)
        { //排气扇打开后,才能停止排气扇
            ExhaustFanStep = 0;
            // ExhaustFanClock = FanClose_Delay_Time; //10min = 60s * 10 = 600s,多10s用于显示OFF
            // if(RTD[0].status != Pt_HighTemp) ExhaustFanClock = 0;
            ExhaustFanClock = 0;
        }
    }
    switch (ExhaustFanStep)
    {
        case 0:
            if (ExhaustFanClock > 0)
            { //延迟10min
                ExhaustFanOpen;
                LowTemp_Ctrl = 0; //延迟低盐检测10min
            }
            else
            { //关闭排气扇
                ExhaustFanClose;
            }
            break;
        case 1:
            if(UI_System.Grill_Smoke == State_Grill_Smoke)
            {
                if(FanClock_Smoke == 0) FanClock_Smoke++;
                if(FanClock_Smoke > 0)
                { 
                    if(FanClock_Smoke <= 5) ExhaustFanOpen;
                    else if(FanClock_Smoke <= (5 + 20))
                    {
                        ExhaustFanClose;
                        if(FanClock_Smoke >= (5 + 20)) FanClock_Smoke = 0; 
                    }
                }
            } 
            else
            {
                ExhaustFanOpen;
                if(FanClock_Smoke > 0) FanClock_Smoke = 0;
            }
            break;
        default:
            ExhaustFanStep = 0;
            break;
    }
}
